home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / goodies / offscreen.win / application.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  48.5 KB  |  1,444 lines

  1. /*
  2.     File:        Offscreen.c
  3.  
  4.     Contains:    QuickTime 3.0 Offscreen sample application.
  5.  
  6.     Written by:    Scott Kuechle
  7.                 based on MDIPlayer code by Brian S. Friedkin
  8.  
  9.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.        <2>         5/18/98        rtm        minor tweaks to GetBitDepthOfBitmap and DrawBackgroundBitmap to get this code
  14.                                        working with the Metrowerks compiler
  15.        <1>         4/24/98        srk        first file; revised to personal coding style
  16.         
  17.  
  18.  NOTES:
  19.  
  20.  
  21.  TO DO:
  22.  
  23. */
  24.  
  25.  
  26. #include "Application.h"
  27. #include "QTCode.h"
  28.  
  29.  
  30. long FAR PASCAL FrameWndProc  (HWND, UINT, UINT, LONG) ;
  31. long FAR PASCAL MovieWndProc  (HWND, UINT, UINT, LONG) ;
  32. BOOL            DoOpenMovie();
  33. int                DoIdleMenus(HWND hWnd, HMENU hMenu);
  34. static void        DoCut(HWND);
  35. static void        DoCopy(HWND);
  36. static void        DoPaste(HWND);
  37. static void        DoClear(HWND);
  38. static void        DoUndo(HWND);
  39. static void        DoAbout(void);
  40. HPALETTE        DoCreatePaletteFromBitMap(HMODULE appInstance, WORD bitMapID);
  41. void            SetMovieFrameTimeValue(Movie theMovie, TimeValue thisPoint);
  42. WORD            GetBitDepthOfBitmap(HMODULE appInstance, WORD bitMapID);
  43. void            GetRBGColorsFromBitmap(HDC    hDC, HANDLE    hInst, WORD    bitMapID, LPRGBQUAD    *srcRgbQuadArray, HPALETTE    *hPalette);
  44. void            DoEraseRect(HDC    hDC, RECT *theRect);
  45. int                GetLineHeight(HDC hDC);
  46. void            DrawMovieAndBackground(HGLOBAL hWinStorage, HDC hDC, HWND hwnd);
  47.  
  48.  
  49.     /* globals for this module */
  50. HANDLE        ghInst                    = NULL;
  51. HWND        ghWndFrame                = NULL;
  52. HWND        ghWndMDIClient            = NULL;
  53. BOOL        gWeAreSizingWindow        = 0;
  54. BOOL        gWeAreCreatingWindow    = 0;
  55. int            gOpenMovieCount            = 0;
  56. char        gAppName[20];
  57. char        gChildName[20];
  58. LPRGBQUAD    gSrcRgbQuadArray        = NULL;        /* rbg color values for our window background bitmap */
  59. HPALETTE    gHBackgroundPalette        = NULL;        /* color palette for our window background */
  60. HANDLE        ghBkgrndBitMap            = NULL;        /* bitmap we paint on the background of our client windows */
  61.  
  62. /* ---------------------------------------------------------------- */
  63. /*                                                                  */
  64. /*    WinMain()                                                     */
  65. /*                                                                  */
  66. /*                                                                  */
  67. /*    The main function for this application                        */
  68. /*                                                                  */
  69. /*                                                                  */
  70. /*                                                                  */
  71. /* ---------------------------------------------------------------- */
  72.  
  73. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  74.                     LPSTR lpszCmdLine, int nCmdShow)
  75.     {
  76.     HANDLE        hAccel ;
  77.     HWND        hwndFrame;
  78.     MSG            msg ;
  79.     WNDCLASSEX    wc;
  80.     BOOL        success;
  81.  
  82.         ghInst = hInstance ;
  83.  
  84.         if (!hPrevInstance) 
  85.         {
  86.             LoadString(hInstance, IDS_APPNAME, gAppName, sizeof(gAppName));
  87.             
  88.             // Register the frame window class
  89.             wc.cbSize        = sizeof(WNDCLASSEX);
  90.             wc.style         = CS_HREDRAW | CS_VREDRAW;
  91.             wc.lpfnWndProc   = (WNDPROC)FrameWndProc;
  92.             wc.cbClsExtra    = 0;
  93.             wc.cbWndExtra    = 0;
  94.             wc.hInstance     = hInstance;
  95.             wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
  96.             wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  97.             wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  98.             wc.lpszMenuName  = gAppName;
  99.             wc.lpszClassName = gAppName;
  100.             wc.hIconSm       = LoadImage(hInstance,
  101.                                          MAKEINTRESOURCE(IDI_APPICON),
  102.                                          IMAGE_ICON,
  103.                                          16, 16,
  104.                                          0);
  105.             if (!RegisterClassEx(&wc))
  106.             {
  107.                 if (!RegisterClass((LPWNDCLASS)&wc.style))
  108.                     return FALSE;
  109.             }
  110.  
  111.             LoadString(hInstance, IDS_MDICHILD, gChildName, sizeof(gChildName));
  112.  
  113.             // Register the Movie child window class
  114.             wc.cbSize        = sizeof(WNDCLASSEX);
  115.             wc.style         = CS_HREDRAW | CS_VREDRAW;
  116.             wc.lpfnWndProc   = (WNDPROC)MovieWndProc;
  117.             wc.cbClsExtra    = 0;
  118.             wc.cbWndExtra    = 0;
  119.             wc.hInstance     = hInstance;
  120.             wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHILDICON));
  121.             wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  122.             wc.hbrBackground = NULL    /* we want to handle erasing of the background ourselves */;
  123.             wc.lpszMenuName  = NULL;
  124.             wc.lpszClassName = gChildName;
  125.             wc.hIconSm       = LoadImage(hInstance,
  126.                                          MAKEINTRESOURCE(IDI_CHILDICON),
  127.                                          IMAGE_ICON,
  128.                                          16, 16,
  129.                                          0);
  130.             if (!RegisterClassEx(&wc))
  131.             {
  132.                 if (!RegisterClass((LPWNDCLASS)&wc.style))
  133.                     return FALSE;
  134.             }
  135.         }
  136.  
  137.         // Load accelerators
  138.         hAccel = LoadAccelerators (hInstance, gAppName);
  139.  
  140.         // Create the main frame window
  141.         ghWndFrame = hwndFrame = CreateWindow (gAppName, gAppName,
  142.                                                WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  143.                                                CW_USEDEFAULT, CW_USEDEFAULT,
  144.                                                CW_USEDEFAULT, CW_USEDEFAULT,
  145.                                                NULL, NULL, hInstance, NULL) ;
  146.  
  147.             /* get background bitmap for use with our client windows */
  148.         ghBkgrndBitMap = LoadResource(ghInst, FindResource(ghInst, MAKEINTRESOURCE(IDB_BITMAP2), RT_BITMAP) );
  149.  
  150.             /* Show the window */
  151.         ShowWindow(hwndFrame, nCmdShow);
  152.         UpdateWindow(hwndFrame);
  153.  
  154.             /* Initialize QuickTime */
  155.         success = QTCode_DoQTInit();
  156.         if (success)
  157.         {
  158.                 /* Process messages */
  159.             while (GetMessage(&msg, NULL, 0, 0))
  160.             {
  161.                 if (!TranslateMDISysAccel(ghWndMDIClient, &msg))
  162.                     if (!TranslateAccelerator(hwndFrame, hAccel, &msg))
  163.                     {
  164.                         TranslateMessage(&msg);
  165.                         DispatchMessage(&msg);
  166.                     }
  167.             }
  168.         }
  169.         else
  170.         {
  171.             MessageBox(hwndFrame, "Quicktime 3.0 not available", "", MB_OK);
  172.         }
  173.  
  174.             /* QuickTime clean up */
  175.         QTCode_QTCleanUp();
  176.  
  177.         return msg.wParam;
  178. }
  179.  
  180. /* ---------------------------------------------------------------- */
  181. /*                                                                  */
  182. /*    FrameWndProc()                                                */
  183. /*                                                                  */
  184. /*                                                                  */
  185. /*    The window procedure for the MDI frame window                 */
  186. /*                                                                  */
  187. /*                                                                  */
  188. /*                                                                  */
  189. /* ---------------------------------------------------------------- */
  190.  
  191. long FAR PASCAL FrameWndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
  192. {
  193.     HWND               hwndChild ;
  194.  
  195.     switch (message)
  196.     {
  197.         case WM_CREATE:          // Create the client window
  198.         {
  199.             CLIENTCREATESTRUCT ccs = {0};
  200.  
  201.             ccs.hWindowMenu  = GetSubMenu(GetMenu(hwnd), WINDOWMENU);
  202.             ccs.idFirstChild = IDM_WINDOWCHILD;
  203.  
  204.             // Create the MDI client filling the client area
  205.             ghWndMDIClient = CreateWindow("mdiclient",
  206.                                          NULL,
  207.                                          WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL |
  208.                                          WS_HSCROLL,
  209.                                          0, 0, 0, 0,
  210.                                          hwnd,
  211.                                          (HMENU)0xCAC,
  212.                                          ghInst,
  213.                                          (LPVOID)&ccs);
  214.  
  215.             ShowWindow(ghWndMDIClient, SW_SHOW);
  216.         }
  217.         return 0 ;
  218.  
  219.         case WM_COMMAND:
  220.             switch (LOWORD(wParam))
  221.             {
  222.                 case IDM_FILEOPEN:
  223.                     DoOpenMovie();
  224.                     return 0 ;
  225.  
  226.                 case IDM_FILECLOSE:
  227.                     hwndChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L) ;
  228.                     if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0L))
  229.                     {
  230.                         SendMessage (ghWndMDIClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0L) ;
  231.                     }
  232.                     return 0 ;
  233.  
  234.                 case IDM_EXIT:
  235.                     SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
  236.                     return 0 ;
  237.  
  238.                 case IDM_WINDOWTILE:
  239.                     SendMessage (ghWndMDIClient, WM_MDITILE, 0, 0L) ;
  240.                     return 0 ;
  241.  
  242.                 case IDM_WINDOWCASCADE:
  243.                     SendMessage (ghWndMDIClient, WM_MDICASCADE, 0, 0L) ;
  244.                     return 0 ;
  245.  
  246.                 case IDM_WINDOWICONS:
  247.                     SendMessage (ghWndMDIClient, WM_MDIICONARRANGE, 0, 0L) ;
  248.                     return 0 ;
  249.  
  250.                 case IDM_WINDOWCLOSEALL:
  251.                     {
  252.                         HWND    hwndT;
  253.             
  254.                         while (hwndT = GetWindow(ghWndMDIClient, GW_CHILD))
  255.                         {
  256.                             // Skip the icon and title windows
  257.                             while (hwndT && GetWindow(hwndT, GW_OWNER))
  258.                                 hwndT = GetWindow(hwndT, GW_HWNDNEXT);
  259.  
  260.                             if (!hwndT) break;
  261.  
  262.                             SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)hwndT, 0L);
  263.                         }
  264.                     }
  265.                     return 0;
  266.  
  267.                 case IDM_ABOUT:
  268.                     DoAbout();
  269.                     return 0;
  270.  
  271.                 default:            // Pass to active child
  272.                     hwndChild = (HWND)SendMessage (ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L) ;
  273.                     if (IsWindow (ghWndMDIClient))
  274.                         SendMessage (hwndChild, WM_COMMAND, wParam, lParam) ;
  275.  
  276.                     break ;        // and then to DefFrameProc
  277.             }
  278.             break ;
  279.  
  280.         case WM_INITMENU:
  281.             if (GetMenu(hwnd) == (HMENU)wParam)
  282.                 return DoIdleMenus((HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0), (HMENU)wParam);
  283.             return 1;
  284.  
  285.         case WM_DESTROY :
  286.             PostQuitMessage (0) ;
  287.             return 0 ;
  288.     }
  289.  
  290.     return DefFrameProc (hwnd, ghWndMDIClient, message, wParam, lParam) ;
  291. }
  292.  
  293. /* ---------------------------------------------------------------- */
  294. /*                                                                  */
  295. /*    MovieWndProc()                                                */
  296. /*                                                                  */
  297. /*                                                                  */
  298. /*    The window procedure for our movie window                     */
  299. /*                                                                  */
  300. /*                                                                  */
  301. /*                                                                  */
  302. /* ---------------------------------------------------------------- */
  303.  
  304. long FAR PASCAL MovieWndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
  305. {
  306.     HGLOBAL            hWinStorage = NULL;
  307.     ChildWindowPtr    childWinPtr = NULL;
  308.     MSG                msg = {0};
  309.  
  310.  
  311.     hWinStorage = (HGLOBAL)GetWindowLong(hwnd, GWL_USERDATA);
  312.  
  313.     switch (message)
  314.     {
  315.         case WM_CREATE:
  316.             {
  317.                 GrafPtr gp;
  318.  
  319.                         /* Tuck away some private storage */
  320.                     hWinStorage = GlobalAlloc(GMEM_MOVEABLE + GMEM_ZEROINIT, sizeof(ChildWindowRecord));
  321.                     SetWindowLong(hwnd, GWL_USERDATA, (LPARAM)hWinStorage);
  322.  
  323.                         /* Associate a GrafPort with this window */
  324.                     gp = QTCode_DoCreatePortAssociation(hwnd, NULL, 0);
  325.  
  326.             }
  327.             return 0;
  328.  
  329.         case WM_GETMINMAXINFO:
  330.             {                
  331.                 if (hWinStorage != NULL)
  332.                 {
  333.                     childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage);
  334.                     if (childWinPtr != NULL)
  335.                     {
  336.                         LPMINMAXINFO lpmmi;
  337.  
  338.                             lpmmi = (LPMINMAXINFO) lParam;
  339.                                 /* we restrict the grow size of our window */
  340.                             lpmmi->ptMaxSize.x = childWinPtr->maxWindowWidth;
  341.                             lpmmi->ptMaxSize.y = childWinPtr->maxWindowHeight;
  342.                             lpmmi->ptMaxTrackSize.x = childWinPtr->maxWindowWidth;
  343.                             lpmmi->ptMaxTrackSize.y = childWinPtr->maxWindowHeight;
  344.  
  345.                             GlobalUnlock(hWinStorage);
  346.                     }
  347.                 }
  348.             }
  349.             return 0;
  350.  
  351.         case WM_PAINT:
  352.             {
  353.                 PAINTSTRUCT    lPaint;
  354.                 HDC            hDC;
  355.  
  356.                     hDC = BeginPaint(hwnd, &lPaint);
  357.                     if (hDC != NULL)
  358.                     {
  359.                         DrawMovieAndBackground(hWinStorage, hDC, hwnd);
  360.                     }
  361.                     EndPaint(hwnd, &lPaint);
  362.             }
  363.             return 0;
  364.  
  365.         case WM_WINDOWPOSCHANGING:
  366.             // Don't show the window until we have created a movie and therefore
  367.             // can properly size the window to contain the movie.
  368.             if (gWeAreCreatingWindow)
  369.             {
  370.                 WINDOWPOS    *lpWindowPos = (WINDOWPOS*)lParam;
  371.                 lpWindowPos->flags &= ~SWP_SHOWWINDOW;
  372.                 return 0;
  373.             }
  374.  
  375.  
  376.             return 0;
  377.     
  378.         case WM_KEYDOWN:
  379.             if (wParam == VK_RETURN)    /* return key was pressed */
  380.             {
  381.                 HDC        hDC            = NULL;
  382.                 OSType    mediaType    = VideoMediaType;
  383.  
  384.                     if (hWinStorage != NULL)
  385.                     {
  386.                         childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage);
  387.                         if (childWinPtr != NULL)
  388.                         {
  389.                                 /* move to next interesting movie time to display */
  390.                             childWinPtr->currentTime = 
  391.                                 QTCode_DoGetMovieNextInterestingTime(childWinPtr->currentTime, childWinPtr->movie,
  392.                                                                         VideoMediaType);
  393.                             GlobalUnlock(hWinStorage);
  394.  
  395.                             hDC = GetDC(hwnd);
  396.                             if (hDC != NULL)
  397.                             {
  398.                                 DrawMovieAndBackground(hWinStorage, hDC, hwnd);
  399.                                 ReleaseDC(hwnd, hDC);
  400.                             }
  401.                         }
  402.                     }
  403.             }
  404.  
  405.             return 0;
  406.  
  407.         case WM_SIZE:
  408.             {                
  409.                 if (hWinStorage != NULL)
  410.                 {
  411.                     childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage);
  412.                     if (childWinPtr != NULL)
  413.                     {
  414.                         if (childWinPtr->movie)
  415.                         {
  416.                             QTCode_PositionMovieRectInClientWindow(childWinPtr->movie, hwnd);
  417.                         }
  418.                         GlobalUnlock(hWinStorage);
  419.                     }
  420.                 }
  421.             }
  422.             return 0;
  423.  
  424.         case WM_ERASEBKGND:
  425.             {
  426.                 /* we don't want the background erased when the window is
  427.                     re-sized, so we'll trap calls here for the WM_ERASEBKGND
  428.                     event */
  429.             }
  430.             return (1);    /* tell GDI we've handled erasing ourselves */
  431.  
  432.         case WM_COMMAND:
  433.             {
  434.                 switch(LOWORD(wParam))        // Undo, Cut, Copy, Paste and Clear
  435.                 {
  436.                     case IDM_EDITUNDO:
  437.                         DoUndo(hwnd);
  438.                         break;
  439.  
  440.                     case IDM_EDITCUT:
  441.                         DoCut(hwnd);
  442.                         break;
  443.  
  444.                     case IDM_EDITCOPY:
  445.                         DoCopy(hwnd);
  446.                         break;
  447.  
  448.                     case IDM_EDITPASTE:
  449.                         DoPaste(hwnd);
  450.                         break;
  451.  
  452.                     case IDM_EDITCLEAR:
  453.                         DoClear(hwnd);
  454.                         break;
  455.                 }
  456.             }
  457.             break;
  458.  
  459.         case WM_DESTROY:
  460.             {        
  461.                 if (hWinStorage != NULL)
  462.                 {
  463.                     childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage);
  464.                     if (childWinPtr != NULL)
  465.                     {
  466.                             /* One less movie open */
  467.                         --gOpenMovieCount;
  468.  
  469.                         QTCode_DisposeMovieAndController(childWinPtr->movie, childWinPtr->refNum);
  470.                             /* Destroy the port association */
  471.                         QTCode_DoDestroyPortAssociation(hwnd);
  472.                             /* clean up offscreen GWorld */
  473.                         QTCode_DoDestroyOffscreen(childWinPtr->offscreenGWorld, childWinPtr->hBitmap);
  474.  
  475.                         SetWindowLong(hwnd, GWL_USERDATA, 0);
  476.                         GlobalUnlock(hWinStorage);
  477.                         GlobalFree((HGLOBAL)GetWindowLong(hwnd, GWL_USERDATA));
  478.                     }
  479.                 }
  480.             }
  481.             return 0;
  482.     }
  483.  
  484.     return DefMDIChildProc (hwnd, message, wParam, lParam);
  485. }
  486.  
  487. /* ---------------------------------------------------------------- */
  488. /*                                                                  */
  489. /*    DoOpenMovie()                                                 */
  490. /*                                                                  */
  491. /*                                                                  */
  492. /*    Code to open a given movie and prepare it for display in a    */
  493. /*    window                                                        */
  494. /*                                                                  */
  495. /*                                                                  */
  496. /* ---------------------------------------------------------------- */
  497.  
  498. BOOL DoOpenMovie()
  499. {
  500.     DWORD            dwVersion;
  501.     short            len;
  502.     char            szPathName[256], szFileName[256];
  503.     HWND            hwndChild = 0;
  504.     OPENFILENAME    ofn = {0};
  505.     HDC                hDC;
  506.     HGLOBAL            hWinStorage = NULL;
  507.     OSErr            err;
  508.     Movie            movie = NULL;
  509.     short            movieRefNum;
  510.     short            movieResId;
  511.     int                movWidth, movHeight;
  512.  
  513.         // Present the dialog...
  514.         *szPathName = 0;
  515.         ofn.lStructSize = sizeof(OPENFILENAME);
  516.         ofn.hwndOwner = ghWndFrame;
  517.         ofn.lpstrFile = (LPSTR)szPathName;
  518.         ofn.nMaxFile  = sizeof(szPathName);
  519.         ofn.lpstrFilter  = "QuickTime Movies (*.mov) \0 *.mov\0All Files (*.*) \0 *.*\0";
  520.         ofn.nFilterIndex = 1;
  521.         ofn.lpstrInitialDir = NULL;
  522.         ofn.Flags        = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  523.         if (!GetOpenFileName(&ofn)) goto bail;
  524.  
  525.         err = QTCode_NewMovieFromWinPathname(szPathName,    /* c-string path to movie */
  526.                                             &movie,            /* Movie returned here */
  527.                                             &movieRefNum,    /* Movie RefNum returned here */
  528.                                             &movieResId);    /* Movie Resource ID returned here */
  529.         if (err == noErr)
  530.         {
  531.             Rect    movieBounds;
  532.  
  533.                 GetMovieBox(movie, &movieBounds);
  534.                 movWidth = RECT_WIDTH(movieBounds);
  535.                 movHeight = RECT_HEIGHT(movieBounds);
  536.         }
  537.         // Create the child movie window
  538.         dwVersion = GetVersion();
  539.         gWeAreCreatingWindow = TRUE;
  540.         if ((dwVersion < 0x80000000) || (LOBYTE(LOWORD(dwVersion)) < 4))
  541.         {
  542.             // This is Windows NT or Win32s, so use the WM_MDICREATE message
  543.             MDICREATESTRUCT mcs;
  544.  
  545.             mcs.szClass = gChildName;
  546.             mcs.szTitle = szFileName; 
  547.             mcs.hOwner  = ghInst;
  548.             mcs.x       = CW_USEDEFAULT;
  549.             mcs.y       = CW_USEDEFAULT;
  550.             mcs.cx      = movWidth + kWinSpacer;    /* set an appropriate width for our movie window */
  551.             mcs.cy      = movHeight + kWinSpacer;    /* set an appropriate height for our movie window */
  552.             mcs.style   = 0;
  553.             mcs.lParam  = 0;
  554.  
  555.             hwndChild = (HWND) SendMessage(ghWndMDIClient,
  556.                                            WM_MDICREATE,
  557.                                            0,
  558.                                            (LPARAM)(LPMDICREATESTRUCT) &mcs);
  559.         }
  560.         else
  561.         {
  562.             // This method will only work with Windows 95, not Windows NT or Win32s
  563.             hwndChild = CreateWindowEx(WS_EX_MDICHILD,
  564.                                        gChildName,
  565.                                        szFileName,
  566.                                        0,
  567.                                        CW_USEDEFAULT,
  568.                                        CW_USEDEFAULT,
  569.                                        movWidth + kWinSpacer,    /* set an appropriate width for our movie window */
  570.                                        movHeight + kWinSpacer,    /* set an appropriate height for our movie window */
  571.                                        ghWndMDIClient, 
  572.                                        NULL,
  573.                                        ghInst,
  574.                                        0);
  575.         }
  576.         gWeAreCreatingWindow = FALSE;
  577.         if (!hwndChild) goto bail;
  578.  
  579.         // Set the window title to the movie filename
  580.         len = strlen(szPathName);
  581.         while (len--)
  582.         {
  583.             char c = szPathName[len];
  584.             if (c == 0x5c || c == '/')
  585.             {
  586.                 strcpy(szFileName, &szPathName[len+1]);
  587.                 break;
  588.             }
  589.         }
  590.         SetWindowText(hwndChild, szFileName);
  591.  
  592.             // Store movie info in private window record
  593.         hWinStorage = (HGLOBAL)GetWindowLong(hwndChild, GWL_USERDATA);
  594.         if (hWinStorage != NULL)
  595.         {
  596.             ChildWindowPtr    childWinPtr = NULL;
  597.  
  598.             childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage);
  599.             if (childWinPtr != NULL)
  600.             {
  601.  
  602.                 childWinPtr->ghInst    = ghInst;
  603.  
  604.                 if (movie != NULL)
  605.                 {
  606.                     childWinPtr->movie = movie;
  607.                     childWinPtr->refNum = movieRefNum;
  608.                     childWinPtr->hBkgrndBitmap = ghBkgrndBitMap;
  609.                     childWinPtr->maxWindowWidth = movWidth + kWinSpacer;
  610.                     childWinPtr->maxWindowHeight = movHeight + kWinSpacer;
  611.  
  612.  
  613.                     QTCode_PositionMovieRectInClientWindow(childWinPtr->movie, hwndChild);
  614.                     err = QTCode_GetStartPointOfFirstVideoSample(childWinPtr->movie, &childWinPtr->currentTime);
  615.                 }
  616.  
  617.  
  618.                 hDC = GetDC(hwndChild);
  619.                 if (hDC != NULL)
  620.                 {
  621.                     WORD bitDepthDC;
  622.                     RECT windowRect;
  623.                     QDErr err;
  624.  
  625.                         GetRBGColorsFromBitmap(    hDC,
  626.                                                 ghInst,
  627.                                                 IDB_BITMAP2,        /* ID of background bitmap we want to use */
  628.                                                 &childWinPtr->srcRgbQuadArray,    /* on return, a pointer to a rgbquad
  629.                                                                                 structure for this bitmap */
  630.                                                 &childWinPtr->hBackgroundPalette);    /* if bitmap bit depth <= 8, a custom palette */
  631.                         bitDepthDC = GetDCBitDepth(hDC);
  632.                         GetWindowRect(hwndChild, &windowRect);
  633.                         childWinPtr->hBitmap = DoCreateDIBSection(hDC,                /* the device context for this HWND */
  634.                                                                     childWinPtr->srcRgbQuadArray,        /* pointer to RGBQUAD array to use when creating
  635.                                                                                                             DIB - NULL if bit depth > 8 */
  636.                                                                     bitDepthDC,                /* screen depth setting */
  637.                                                                     RECT_WIDTH(windowRect),    /* window width */
  638.                                                                     RECT_HEIGHT(windowRect)    /* window height */
  639.                                                                     );
  640.                         childWinPtr->hMemDC = DoCreateMemoryDC(hwndChild);
  641.                         SelectObject(childWinPtr->hMemDC, childWinPtr->hBitmap);
  642.                         err = QTCode_CreateOffscreen(&childWinPtr->offscreenGWorld,
  643.                                                     NULL,
  644.                                                     NULL,
  645.                                                     0,
  646.                                                     childWinPtr->hBitmap,/* a pointer to a valid bitmap or NULL */
  647.                                                     childWinPtr->hMemDC);    /* a pointer to a valid device context or NULL */
  648.                         QTCode_SetMovieGWorld(childWinPtr->movie, childWinPtr->offscreenGWorld);
  649.  
  650.                         ReleaseDC(hwndChild, hDC);
  651.                 }
  652.  
  653.                 GlobalUnlock(hWinStorage);
  654.             }
  655.         }
  656.         SetWindowLong(hwndChild, GWL_USERDATA, (LPARAM)hWinStorage);
  657.  
  658.         // Show the window
  659.         ShowWindow(hwndChild, SW_SHOW);
  660.         UpdateWindow(hwndChild);
  661.         SetFocus(hwndChild);
  662.  
  663.         // One more window has been opened
  664.         gOpenMovieCount += 1;
  665.  
  666.         return TRUE;
  667.  
  668.         bail:
  669.             if (hwndChild) SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0L);
  670.  
  671.         return FALSE;
  672. }
  673.  
  674.  
  675. /* ---------------------------------------------------------------- */
  676. /*                                                                  */
  677. /*    DrawMovieAndBackground()                                      */
  678. /*                                                                  */
  679. /*                                                                  */
  680. /*    Code to display a movie and background image in a given       */
  681. /*    window                                                        */
  682. /*                                                                  */
  683. /*                                                                  */
  684. /* ---------------------------------------------------------------- */
  685.  
  686. void DrawMovieAndBackground(HGLOBAL hWinStorage, HDC hDC, HWND hwnd)
  687. {
  688.     HPALETTE        previousPalette    = NULL;
  689.     ChildWindowPtr    childWinPtr;
  690.  
  691.         if ((childWinPtr = (ChildWindowPtr)GlobalLock(hWinStorage)) != NULL)
  692.             {
  693.                 RECT    clientRect, windowRect;
  694.                 Rect    movieBounds;
  695.                 
  696.                     previousPalette = UseCustomPalette(hDC, childWinPtr->hBackgroundPalette);
  697.  
  698.                     GetClientRect(hwnd, &clientRect);
  699.                     GetWindowRect(hwnd, &windowRect);
  700.  
  701.                     DrawBackgroundBitmap(childWinPtr->hMemDC, hwnd, childWinPtr->hBkgrndBitmap, &clientRect);
  702.                     DrawHelpMessage(childWinPtr->hMemDC, hwnd);
  703.  
  704.                     GetMovieBox(childWinPtr->movie, &movieBounds);
  705.                     DoDrawFrameInfo(childWinPtr->hMemDC, hwnd, &movieBounds, childWinPtr->currentTime);
  706.  
  707.                     SetMovieTimeValue(childWinPtr->movie, childWinPtr->currentTime);
  708.                     QTCode_ForceMovieRedraw(childWinPtr->movie);
  709.  
  710.                         /* copy our memory DC image to the display DC */
  711.                     BitBlt(hDC, 0, 0, RECT_WIDTH(windowRect), RECT_HEIGHT(windowRect), childWinPtr->hMemDC,
  712.                             0, 0, SRCCOPY);
  713.  
  714.                     GlobalUnlock(hWinStorage);
  715.             }
  716.  
  717. }
  718.  
  719. /* ---------------------------------------------------------------- */
  720. /*                                                                  */
  721. /*    DoCut()                                                       */
  722. /*                                                                  */
  723. /*                                                                  */
  724. /*    Handles clipboard "cut" operations                            */
  725. /*                                                                  */
  726. /*                                                                  */
  727. /*                                                                  */
  728. /* ---------------------------------------------------------------- */
  729.  
  730. static void DoCut(HWND hwnd)
  731. {
  732. }
  733.  
  734. /* ---------------------------------------------------------------- */
  735. /*                                                                  */
  736. /*    DoCopy()                                                      */
  737. /*                                                                  */
  738. /*                                                                  */
  739. /*    Handles clipboard "copy" operations                           */
  740. /*                                                                  */
  741. /*                                                                  */
  742. /*                                                                  */
  743. /* ---------------------------------------------------------------- */
  744.  
  745. static void DoCopy(HWND hwnd)
  746. {
  747. }
  748.  
  749. /* ---------------------------------------------------------------- */
  750. /*                                                                  */
  751. /*    DoPaste()                                                     */
  752. /*                                                                  */
  753. /*                                                                  */
  754. /*    Handles clipboard "paste" operations                          */
  755. /*                                                                  */
  756. /*                                                                  */
  757. /*                                                                  */
  758. /* ---------------------------------------------------------------- */
  759.  
  760. static void DoPaste(HWND hwnd)
  761. {
  762. }
  763.  
  764. /* ---------------------------------------------------------------- */
  765. /*                                                                  */
  766. /*    DoClear()                                                     */
  767. /*                                                                  */
  768. /*                                                                  */
  769. /*    Handles clipboard "clear" operations                          */
  770. /*                                                                  */
  771. /*                                                                  */
  772. /*                                                                  */
  773. /* ---------------------------------------------------------------- */
  774.  
  775. static void DoClear(HWND hwnd)
  776. {
  777. }
  778.  
  779. /* ---------------------------------------------------------------- */
  780. /*                                                                  */
  781. /*    DoUndo()                                                      */
  782. /*                                                                  */
  783. /*                                                                  */
  784. /*    Handles clipboard "undo" operations                           */
  785. /*                                                                  */
  786. /*                                                                  */
  787. /*                                                                  */
  788. /* ---------------------------------------------------------------- */
  789.  
  790. static void DoUndo(HWND hwnd)
  791. {
  792. }
  793.  
  794.  
  795. /* ---------------------------------------------------------------- */
  796. /*                                                                  */
  797. /*    DoIdleMenus()                                                 */
  798. /*                                                                  */
  799. /*                                                                  */
  800. /*    Enable the close item if there are any movie windows opened   */
  801. /*                                                                  */
  802. /*                                                                  */
  803. /*                                                                  */
  804. /* ---------------------------------------------------------------- */
  805.  
  806. int DoIdleMenus(HWND hWnd, HMENU hMenu)
  807. {
  808.         /* Enable the close item if there are any movie windows opened */
  809.     EnableMenuItem(hMenu, IDM_FILECLOSE, (gOpenMovieCount) ? MF_ENABLED : MF_GRAYED);
  810.  
  811.     return 0;
  812. }
  813.  
  814. /* ---------------------------------------------------------------- */
  815. /*                                                                  */
  816. /*    DialogProc()                                                  */
  817. /*                                                                  */
  818. /*                                                                  */
  819. /*    Callback for our dialog box                                   */
  820. /*                                                                  */
  821. /*                                                                  */
  822. /*                                                                  */
  823. /* ---------------------------------------------------------------- */
  824.  
  825. static LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  826. {
  827.     switch (message)
  828.     {
  829.         case WM_COMMAND:
  830.             switch (LOWORD(wParam))
  831.             {
  832.                 case IDOK:
  833.                     EndDialog(hDlg, IDOK);
  834.                     break;
  835.             }
  836.             break;
  837.     }
  838.  
  839.     return 0;
  840. }
  841.  
  842. /* ---------------------------------------------------------------- */
  843. /*                                                                  */
  844. /*    DoAbout()                                                     */
  845. /*                                                                  */
  846. /*                                                                  */
  847. /*    Displays a dialog box with information about our program      */
  848. /*                                                                  */
  849. /*                                                                  */
  850. /*                                                                  */
  851. /* ---------------------------------------------------------------- */
  852.  
  853. static void DoAbout()
  854. {
  855.     DialogBox(ghInst, MAKEINTRESOURCE(IDD_ABOUT), ghWndFrame, (DLGPROC)DialogProc);
  856. }
  857.  
  858. /* ---------------------------------------------------------------- */
  859. /*                                                                  */
  860. /*    DrawBackgroundBitmap()                                        */
  861. /*                                                                  */
  862. /*                                                                  */
  863. /*    Sets the pixels in the target device context to those from    */
  864. /*    a given DIB                                                   */
  865. /*                                                                  */
  866. /*                                                                  */
  867. /* ---------------------------------------------------------------- */
  868.  
  869. void DrawBackgroundBitmap(    HDC        hDC,
  870.                             HWND    hwnd,
  871.                             HANDLE    hBitMap,
  872.                             RECT    *updateRect)
  873. {
  874.     if ((hBitMap != NULL) && (hDC != NULL) && (hwnd != NULL))
  875.     {
  876.         LPBITMAPINFO    lpBi;
  877.         LPTSTR            lpBits;
  878.         int             x, y, width, height;
  879.         int                success = FALSE;
  880.         RECT            clientRect;
  881.         int                childHeight, childWidth;
  882.  
  883.             GetClientRect(hwnd, &clientRect);
  884.             childWidth = RECT_WIDTH(clientRect);
  885.             childHeight = RECT_HEIGHT(clientRect);
  886.  
  887.             lpBi = (LPBITMAPINFO)LockResource(hBitMap);
  888.  
  889.             lpBits = (LPSTR)lpBi;
  890.             lpBits += lpBi->bmiHeader.biSize + ((1 << lpBi->bmiHeader.biBitCount) * sizeof(RGBQUAD));
  891.             width = lpBi->bmiHeader.biWidth;
  892.             height = lpBi->bmiHeader.biHeight;
  893.  
  894.             for (y = 0; y <= childHeight; y += lpBi->bmiHeader.biHeight)
  895.             {
  896.                 for (x = 0; x <= childWidth; x += lpBi->bmiHeader.biWidth)
  897.                 {
  898.                     BOOL    intersectRect = FALSE;
  899.                     RECT    bitMapRect;
  900.                     RECT    destRect;
  901.                     
  902.                     SetRect(&bitMapRect, x, y, x+lpBi->bmiHeader.biWidth, y+lpBi->bmiHeader.biHeight);
  903.                     
  904.                         intersectRect = IntersectRect( &destRect, // address of structure for intersection 
  905.                                                         updateRect, // address of structure with first rectangle 
  906.                                                         &bitMapRect // address of structure with second rectangle 
  907.                                                     ); 
  908.                             /* does the current rectangle intersect with the update
  909.                                 rectangle? If so, draw it, otherwise, don't */
  910.                         if (intersectRect)
  911.                         {
  912.                             success = SetDIBitsToDevice(hDC, x, y,
  913.                                                         lpBi->bmiHeader.biWidth,
  914.                                                         lpBi->bmiHeader.biHeight,
  915.                                                         0,0,
  916.                                                         0, lpBi->bmiHeader.biHeight,
  917.                                                         lpBits, lpBi,
  918.                                                         DIB_RGB_COLORS);
  919.                         }
  920.                 }
  921.             }
  922.     }
  923.  
  924. }
  925.  
  926. /* ---------------------------------------------------------------- */
  927. /*                                                                  */
  928. /*    DoCreatePaletteFromBitMap()                                   */
  929. /*                                                                  */
  930. /*                                                                  */
  931. /*    Builds a palette from a given bitmap                          */
  932. /*                                                                  */
  933. /*                                                                  */
  934. /*                                                                  */
  935. /* ---------------------------------------------------------------- */
  936.  
  937. HPALETTE DoCreatePaletteFromBitMap(    HMODULE        appInstance,
  938.                                     WORD        bitMapID)
  939. {
  940.     HANDLE hBitMap;
  941.     HPALETTE hPalette = NULL;
  942.  
  943.  
  944.         hBitMap = LoadResource(appInstance,
  945.                                 FindResource(appInstance, MAKEINTRESOURCE(bitMapID), RT_BITMAP) );
  946.         if (hBitMap != NULL)
  947.         {
  948.             LPBITMAPINFO    lpBi;
  949.             HANDLE            hPal;
  950.             LPLOGPALETTE    lpPal;
  951.             int                i, nColorData;
  952.  
  953.                 lpBi = (LPBITMAPINFO)LockResource(hBitMap);
  954.  
  955.                 if (lpBi->bmiHeader.biClrUsed != 0)
  956.                 {
  957.                     nColorData = lpBi->bmiHeader.biClrUsed;
  958.                 }
  959.                 else
  960.                 {
  961.                     switch( lpBi->bmiHeader.biBitCount)
  962.                     {
  963.                         case 1 :
  964.                             nColorData = 2;
  965.                         break;
  966.                     
  967.                         case 4 :
  968.                             nColorData = 16;
  969.                         break;
  970.                     
  971.                         case 8 :
  972.                             nColorData = 256;
  973.                         break;
  974.                     
  975.                         case 24 :
  976.                         case 32 : 
  977.                             nColorData = 0;
  978.                         break;
  979.                     }
  980.                 }
  981.  
  982.                 hPal = GlobalAlloc( GHND, sizeof (LOGPALETTE) + (nColorData * sizeof (PALETTEENTRY)) );
  983.                 lpPal = (LPLOGPALETTE)GlobalLock(hPal);
  984.  
  985.                 lpPal->palVersion = 0x300;
  986.                 lpPal->palNumEntries = nColorData;
  987.  
  988.                 for (i = 0; i < nColorData; i++)
  989.                 {
  990.                     lpPal->palPalEntry[i].peRed        = lpBi->bmiColors[i].rgbRed;
  991.                     lpPal->palPalEntry[i].peGreen    = lpBi->bmiColors[i].rgbGreen;
  992.                     lpPal->palPalEntry[i].peBlue    = lpBi->bmiColors[i].rgbBlue;
  993.  
  994.                 }
  995.  
  996.                 hPalette = CreatePalette( lpPal );
  997.  
  998.                 GlobalUnlock(hPal);
  999.                 GlobalFree(hPal);
  1000.  
  1001.         }
  1002.  
  1003.         return hPalette;
  1004. }
  1005.  
  1006.  
  1007. /* ---------------------------------------------------------------- */
  1008. /*                                                                  */
  1009. /*    DoEraseRect()                                                 */
  1010. /*                                                                  */
  1011. /*                                                                  */
  1012. /*    Code to erase a given windows rectangle                       */
  1013. /*                                                                  */
  1014. /*                                                                  */
  1015. /*                                                                  */
  1016. /* ---------------------------------------------------------------- */
  1017.  
  1018. void DoEraseRect(HDC    hDC,
  1019.                 RECT    *theRect)
  1020. {
  1021.     if (hDC != NULL)
  1022.     {
  1023.         HBRUSH        aBrush;
  1024.             
  1025.                 /* erase rect. for string before redraw */
  1026.             aBrush = CreateSolidBrush(RGB(255,255,255));
  1027.             if (aBrush != NULL)
  1028.             {
  1029.                 FillRect(hDC, theRect, aBrush);
  1030.                 DeleteObject(aBrush);
  1031.             }
  1032.  
  1033.     }
  1034. }
  1035.  
  1036. /* ---------------------------------------------------------------- */
  1037. /*                                                                  */
  1038. /*    GetLineHeight()                                               */
  1039. /*                                                                  */
  1040. /*                                                                  */
  1041. /*    Returns the line height for a given device context            */
  1042. /*                                                                  */
  1043. /*                                                                  */
  1044. /*                                                                  */
  1045. /* ---------------------------------------------------------------- */
  1046.  
  1047. int GetLineHeight(HDC    hDC)
  1048. {
  1049.     TEXTMETRIC    tm;
  1050.  
  1051.         GetTextMetrics(hDC, &tm);
  1052.         return(tm.tmExternalLeading + tm.tmHeight);
  1053. }
  1054.  
  1055. /* ---------------------------------------------------------------- */
  1056. /*                                                                  */
  1057. /*    DrawHelpMessage()                                             */
  1058. /*                                                                  */
  1059. /*                                                                  */
  1060. /*    Draws our help text in a window                               */
  1061. /*                                                                  */
  1062. /*                                                                  */
  1063. /*                                                                  */
  1064. /* ---------------------------------------------------------------- */
  1065.  
  1066. void DrawHelpMessage(    HDC        hDC,
  1067.                         HWND    hwnd)
  1068. {
  1069.  
  1070.     if (hDC != NULL)
  1071.     {
  1072.         RECT        clientRect, targetRect;
  1073.         char        helpText[100] = "Press <enter> to advance to next movie frame";
  1074.         TEXTMETRIC    tm;
  1075.         int            nLineHeight, strWidth;
  1076.  
  1077.             GetClientRect(hwnd, &clientRect);
  1078.             GetTextMetrics(hDC, &tm);
  1079.             nLineHeight = tm.tmExternalLeading + tm.tmHeight;
  1080.  
  1081.             strWidth =  strlen( (LPCTSTR)&helpText ) * tm.tmAveCharWidth;
  1082.             SetRect(&targetRect,    clientRect.left + ((RECT_WIDTH(clientRect) - strWidth)/2),
  1083.                                     clientRect.bottom - nLineHeight,
  1084.                                     clientRect.left + ((RECT_WIDTH(clientRect) - strWidth)/2) + strWidth,
  1085.                                     clientRect.bottom);
  1086.             DoEraseRect(hDC, &targetRect);
  1087.  
  1088.                 /* draw help message */
  1089.             DrawText(hDC, (LPCTSTR)&helpText, -1, &targetRect, DT_CENTER);
  1090.     }
  1091. }
  1092.  
  1093.  
  1094. /* ---------------------------------------------------------------- */
  1095. /*                                                                  */
  1096. /*    DoCreateDIBSection()                                          */
  1097. /*                                                                  */
  1098. /*                                                                  */
  1099. /*    Creates a device independent bitmap using CreateDIBSection    */
  1100. /*                                                                  */
  1101. /*                                                                  */
  1102. /*                                                                  */
  1103. /* ---------------------------------------------------------------- */
  1104.  
  1105. HBITMAP DoCreateDIBSection(    HDC                dc,
  1106.                             LPRGBQUAD        srcRgbQuadArray,    /* if (depth > 8), this param ignored */
  1107.                             WORD            depth,
  1108.                             LONG            width,
  1109.                             LONG            height
  1110.                             )
  1111. {
  1112.     UINT    usage;
  1113.     LPTSTR    bits = NULL;
  1114.        
  1115.         // a struct large enough to hold the largest bitmapinfo ...
  1116.     struct BITMAPINFO_256
  1117.     {   
  1118.         BITMAPINFOHEADER bmiHeader;
  1119.         long bmiColors[256];
  1120.     };
  1121.     typedef struct BITMAPINFO_256 BITMAPINFO_256;
  1122.  
  1123.     BITMAPINFO_256 bmi;
  1124.  
  1125.  
  1126.         memset(&bmi, 0, sizeof(bmi));
  1127.  
  1128.         bmi.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
  1129.         bmi.bmiHeader.biWidth            = width;
  1130.             /* important!!! - we specify a top-down DIB (by passing a negative height value)
  1131.                 with origin in the upper left, otherwise our movie image will show up as inverted */
  1132.         bmi.bmiHeader.biHeight            = -1 * height;
  1133.         bmi.bmiHeader.biPlanes            = 1;
  1134.         bmi.bmiHeader.biBitCount        = depth;
  1135.         bmi.bmiHeader.biSizeImage        = 0;
  1136.         bmi.bmiHeader.biClrUsed            = 0;
  1137.         bmi.bmiHeader.biClrImportant    = 0;
  1138.  
  1139.  
  1140.         switch ( depth )
  1141.         {
  1142.             case 4:
  1143.             case 8:
  1144.                 {
  1145.                     long        num_colors = (1 << depth),
  1146.                                 i;
  1147.                     LPRGBQUAD    lpQuadDest, lpQuadSource;
  1148.  
  1149.  
  1150.                         bmi.bmiHeader.biCompression = BI_RGB;
  1151.                         usage = DIB_RGB_COLORS;
  1152.  
  1153.                         lpQuadSource = srcRgbQuadArray;
  1154.                         
  1155.                         for (i=0; i<num_colors; i++)
  1156.                         {
  1157.                             lpQuadDest = (LPRGBQUAD)&bmi.bmiColors[i];
  1158.  
  1159.                             lpQuadDest->rgbBlue        = lpQuadSource->rgbBlue;
  1160.                             lpQuadDest->rgbRed        = lpQuadSource->rgbRed;
  1161.                             lpQuadDest->rgbGreen    = lpQuadSource->rgbGreen;
  1162.                             lpQuadDest->rgbReserved    = lpQuadSource->rgbReserved;
  1163.  
  1164.                             ++lpQuadSource;
  1165.                         }
  1166.                 }
  1167.                 break;
  1168.  
  1169.             case 16:
  1170.             case 24:
  1171.             case 32:
  1172.                 {                    
  1173.                     bmi.bmiHeader.biCompression = BI_RGB;
  1174.                     usage = DIB_RGB_COLORS;
  1175.         
  1176.                     bmi.bmiColors[0] = 0;
  1177.                     bmi.bmiColors[1] = 0;
  1178.                     bmi.bmiColors[2] = 0;
  1179.                 }
  1180.                 break;
  1181.    
  1182.             default:
  1183.                 break;
  1184.         }
  1185.  
  1186.         return CreateDIBSection(dc, (BITMAPINFO *) &bmi, usage, &bits, NULL, 0);
  1187. }
  1188.  
  1189.  
  1190. /* ---------------------------------------------------------------- */
  1191. /*                                                                  */
  1192. /*    GetDCBitDepth()                                               */
  1193. /*                                                                  */
  1194. /*                                                                  */
  1195. /*    Returns the bit depth of a device context                     */
  1196. /*                                                                  */
  1197. /*                                                                  */
  1198. /*                                                                  */
  1199. /* ---------------------------------------------------------------- */
  1200.  
  1201. WORD    GetDCBitDepth(HDC    hDC)
  1202. {
  1203.     return(GetDeviceCaps( hDC, BITSPIXEL)); 
  1204. }
  1205.  
  1206. /* ---------------------------------------------------------------- */
  1207. /*                                                                  */
  1208. /*    GetBitDepthOfBitmap()                                         */
  1209. /*                                                                  */
  1210. /*                                                                  */
  1211. /*    Returns the bit depth of a bitmap                             */
  1212. /*                                                                  */
  1213. /*                                                                  */
  1214. /*                                                                  */
  1215. /* ---------------------------------------------------------------- */
  1216.  
  1217. WORD    GetBitDepthOfBitmap(HMODULE appInstance,    /* application instance */
  1218.                             WORD bitMapID            /* resource ID of bit map */
  1219.                             )
  1220. {
  1221.     HBITMAP hBitMap;
  1222.  
  1223.         hBitMap = LoadResource(appInstance, FindResource(appInstance, MAKEINTRESOURCE(bitMapID), RT_BITMAP) );
  1224.         if (hBitMap != NULL)
  1225.         {
  1226.             LPBITMAPINFO    lpBi;
  1227.  
  1228.                 lpBi = (LPBITMAPINFO)LockResource(hBitMap);
  1229.  
  1230.                 return (lpBi->bmiHeader.biBitCount);
  1231.         }
  1232.         else
  1233.         {
  1234.             return 0;
  1235.         }
  1236.  
  1237. }
  1238.  
  1239.  
  1240. /* ---------------------------------------------------------------- */
  1241. /*                                                                  */
  1242. /*    GetRBGColorsFromBitmap()                                      */
  1243. /*                                                                  */
  1244. /*                                                                  */
  1245. /*    Returns the RGBQUAD array for a bitmap                        */
  1246. /*                                                                  */
  1247. /*                                                                  */
  1248. /*                                                                  */
  1249. /* ---------------------------------------------------------------- */
  1250.  
  1251. void GetRBGColorsFromBitmap(HDC            hDC,
  1252.                             HANDLE        hInst,
  1253.                             WORD        bitMapID,
  1254.                             LPRGBQUAD    *srcRgbQuadArray,    /* on return, a pointer to a rgbquad
  1255.                                                             structure for this bitmap */
  1256.                             HPALETTE    *hPalette)    /* if bitmap bit depth <= 8, a custom palette
  1257.                                                     for the bitmap will be returned here */
  1258. {
  1259.     WORD            bitDepthDC, bitDepthBITMAP;
  1260.     LPBITMAPINFO    srcBITMAPINFO;
  1261.     HANDLE            hBitMapTemp;
  1262.  
  1263.         bitDepthDC        =    GetDCBitDepth(hDC);
  1264.         bitDepthBITMAP    =    GetBitDepthOfBitmap(hInst,        /* application instance */
  1265.                                                 bitMapID    /* resource ID of bit map */
  1266.                                                 );
  1267.         srcBITMAPINFO = NULL;
  1268.         *srcRgbQuadArray = NULL;
  1269.         *hPalette = NULL;
  1270.  
  1271.             /* does the device context have a bit depth <= 8? */
  1272.         if (bitDepthDC <= 8)
  1273.         {
  1274.                 /* does our bitmap have a depth <= 8? */
  1275.             if (bitDepthBITMAP <= 8)
  1276.             {
  1277.                     /* create custom palette for use with this bitmap */
  1278.                 *hPalette = DoCreatePaletteFromBitMap(hInst, bitMapID);
  1279.  
  1280.                     /* get color data to use when calling CreateDIBSection */
  1281.                 hBitMapTemp    = LoadResource(hInst,
  1282.                                             FindResource(hInst, MAKEINTRESOURCE(bitMapID),
  1283.                                             RT_BITMAP) );
  1284.                 if (hBitMapTemp != NULL)
  1285.                 {
  1286.                         /* get bitmapinfo data */
  1287.                     srcBITMAPINFO = (LPBITMAPINFO)LockResource(hBitMapTemp);
  1288.                         /* get pointer to rgbquad array for this bitmap */
  1289.                     *srcRgbQuadArray = &srcBITMAPINFO->bmiColors[0];
  1290.                 }
  1291.             }
  1292.         }
  1293.  
  1294. }
  1295.  
  1296. /* ---------------------------------------------------------------- */
  1297. /*                                                                  */
  1298. /*    DoCreateMemoryDC()                                            */
  1299. /*                                                                  */
  1300. /*                                                                  */
  1301. /*    Creates a memory device context                               */
  1302. /*                                                                  */
  1303. /*                                                                  */
  1304. /*                                                                  */
  1305. /* ---------------------------------------------------------------- */
  1306.  
  1307. HDC    DoCreateMemoryDC(HWND    hwnd)
  1308. {
  1309.     HDC    hMemDC, hDC;
  1310.  
  1311.         hDC = GetDC(hwnd);
  1312.         if (hDC)
  1313.         {
  1314.             hMemDC = CreateCompatibleDC(hDC);
  1315.             SetMapMode(hMemDC, GetMapMode(hDC));
  1316.             ReleaseDC(hwnd, hDC);
  1317.  
  1318.             return hMemDC;
  1319.         }
  1320.  
  1321.         return NULL;
  1322. }
  1323.  
  1324.  
  1325.  
  1326. /* ---------------------------------------------------------------- */
  1327. /*                                                                  */
  1328. /*    UseCustomPalette()                                            */
  1329. /*                                                                  */
  1330. /*                                                                  */
  1331. /*    Selects/Realizes a logical palette                            */
  1332. /*                                                                  */
  1333. /*                                                                  */
  1334. /*                                                                  */
  1335. /* ---------------------------------------------------------------- */
  1336.  
  1337. HPALETTE UseCustomPalette(HDC    hDC, HPALETTE    newPalette)
  1338. {
  1339.     HPALETTE    previousPalette;
  1340.     UINT        nEntries;
  1341.  
  1342.             /* use a custom palette if need be */
  1343.         if (newPalette)
  1344.         {
  1345.             previousPalette = SelectPalette(hDC, newPalette, FALSE);
  1346.             nEntries = RealizePalette(hDC);
  1347.         }
  1348.  
  1349.         return previousPalette;
  1350. }
  1351.  
  1352. /* ---------------------------------------------------------------- */
  1353. /*                                                                  */
  1354. /*    DoDrawFrameInfo()                                             */
  1355. /*                                                                  */
  1356. /*                                                                  */
  1357. /*    Draws our help text messages into a window                    */
  1358. /*                                                                  */
  1359. /*                                                                  */
  1360. /*                                                                  */
  1361. /* ---------------------------------------------------------------- */
  1362.  
  1363. void DoDrawFrameInfo(HDC        hMemDC,
  1364.                      HWND        hwnd,
  1365.                      Rect        *movieBounds,
  1366.                      TimeValue    theTime)
  1367. {
  1368.     RECT        destRect;
  1369.     int            nLineHeight;
  1370.     Str255         theString;
  1371.     char        frameText[25] = "Frame ";
  1372.     Rect        centeredRect;
  1373.  
  1374.  
  1375.         nLineHeight = GetLineHeight(hMemDC);
  1376.  
  1377.         CenterMovieRectInWindow(hwnd,                    /* window where we are placing the image */
  1378.                               (movieBounds->right - movieBounds->left),
  1379.                               (movieBounds->bottom - movieBounds->top),    /* width, height, of the movie */
  1380.                               ¢eredRect            /* on output, a Mac Rect centered in the window */
  1381.                               );
  1382.         SetRect(&destRect,    (int)centeredRect.left - nLineHeight,
  1383.                             (int)centeredRect.top - nLineHeight /*- menuSize*/,
  1384.                             (int)centeredRect.right + nLineHeight,
  1385.                             (int)centeredRect.bottom + nLineHeight /*- menuSize*/);
  1386.         DoEraseRect(hMemDC, &destRect);
  1387.  
  1388.         SetRect(&destRect,    (int)centeredRect.left,
  1389.                             (int)centeredRect.bottom /*- menuSize*/,
  1390.                             (int)centeredRect.right,
  1391.                             (int)centeredRect.bottom + nLineHeight /*- menuSize*/);
  1392.         DoEraseRect(hMemDC, &destRect);
  1393.  
  1394.             /* draw new frame # */
  1395.         NumToString((long)theTime, theString);
  1396.         p2cstr(theString);
  1397.         lstrcat((LPSTR)frameText, (LPCSTR)&theString);
  1398.         DrawText(hMemDC, (LPCTSTR)&frameText, -1, &destRect, DT_CENTER);
  1399.  
  1400. }
  1401.  
  1402.  
  1403. /* ---------------------------------------------------------------- */
  1404. /*                                                                  */
  1405. /*    CenterMovieRectInWindow()                                     */
  1406. /*                                                                  */
  1407. /*                                                                  */
  1408. /*    Given height/width values for a movie, returns a Mac rect     */
  1409. /*    for the movie centered in a window                            */
  1410. /*                                                                  */
  1411. /*                                                                  */
  1412. /* ---------------------------------------------------------------- */
  1413.  
  1414. void CenterMovieRectInWindow(HWND    hwnd,                    /* window where we are placing the image */
  1415.                               int    movWidth, int movHeight,    /* width, height, of the movie */
  1416.                               Rect    *centeredRect            /* on output, a Mac Rect centered in the window */
  1417.                               )
  1418. {
  1419.     RECT    clientRect;
  1420.     int        availSpace;
  1421.     BOOL    success;
  1422.  
  1423.         success = GetClientRect(hwnd, // handle of window 
  1424.                                 &clientRect// address of structure for client coordinates 
  1425.                                 );    
  1426.  
  1427.         availSpace = RECT_WIDTH(clientRect) - movWidth;
  1428.         if (availSpace < 0)
  1429.         {
  1430.             /* movie is bigger than client space? */
  1431.         }
  1432.         centeredRect->left = clientRect.left + availSpace/2;
  1433.  
  1434.         availSpace = RECT_HEIGHT(clientRect) - movHeight;
  1435.         if (availSpace < 0)
  1436.         {
  1437.             /* movie is bigger than client space? */
  1438.         }
  1439.         centeredRect->top = clientRect.top + availSpace/2;
  1440.         centeredRect->right = centeredRect->left + movWidth;
  1441.         centeredRect->bottom = centeredRect->top + movHeight;
  1442.  
  1443. }
  1444.